package com.seadragon.app.ksr.service.impl;

//
//@Service("searchService")
//@Transactional
//public class SearchServiceHSImpl implements SearchService {
//	private Logger logger = LoggerFactory.getLogger(SearchServiceHSImpl.class);
//
//	@PersistenceContext
//	protected EntityManager entityManager;
//
//	@Autowired
//	private GeocodeService geocodeService;
//
//	@Autowired
//	private AddressService addressService;
//
//	@Autowired
//	private CacheManager cacheManager;
//
//	@Autowired
//	private StateDao stateDao;
//
//	private Query buildAddressQuery(QueryBuilder builder, GeocodedAddress address, int distance) {
//		Query query = null;
//		if (AddressType.ROUTE == address.getAddressType()) {
//			query = builder.spatial().onCoordinates("address.location").within(distance, Unit.KM).ofCoordinates(address).createQuery();
//		} else if (AddressType.NEIGHBORHOOD == address.getAddressType()) {
//			query = builder.bool()
//					.must(builder.keyword().onField("address.neighborhood").matching(address.getNeighborhood()).createQuery())
//					.must(builder.keyword().onField("address.geocodedCity").matching(address.getCity()).createQuery())
//					.must(builder.keyword().onField("address.geocodedState").matching(address.getState()).createQuery()).createQuery();
//		} else if (AddressType.ZIP == address.getAddressType()) {
//			query = builder.keyword().onField("address.geocodedZip").matching(address.getZip()).createQuery();
//		} else if (AddressType.CITY == address.getAddressType()) {
//			query = builder.bool().must(builder.keyword().onField("address.geocodedCity").matching(address.getCity()).createQuery())
//					.must(builder.keyword().onField("address.geocodedState").matching(address.getState()).createQuery()).createQuery();
//		} else if (AddressType.COUNTY == address.getAddressType()) {
//			query = builder.bool().must(builder.keyword().onField("address.geocodedCounty").matching(address.getCounty()).createQuery())
//					.must(builder.keyword().onField("address.geocodedState").matching(address.getState()).createQuery()).createQuery();
//		} else if (AddressType.STATE == address.getAddressType()) {
//			query = builder.keyword().onField("address.geocodedState").matching(address.getState()).createQuery();
//		}
//		return query;
//	}
//
//	private Query buildAddressQuery(QueryBuilder builder, Location targetLocation, List<? extends Location> neighbors, int distance) {
//		Query query = buildLocationQuery(builder, targetLocation, distance);
//		if (neighbors != null) {
//			@SuppressWarnings("rawtypes")
//			BooleanJunction junction = builder.bool().should(query);
//			for (Location location : neighbors) {
//				junction.should(buildLocationQuery(builder, location, distance));
//			}
//			return junction.createQuery();
//		}
//
//		return query;
//	}
//
//	private Query buildLocationQuery(QueryBuilder builder, Location location, int distance) {
//		Query query = null;
//		if (AddressType.ROUTE == location.getLocationType()) {
//			query = builder.spatial().onCoordinates("address.location").within(distance, Unit.KM).ofCoordinates((Address)location).createQuery();
//		} else if (AddressType.ZIP == location.getLocationType()) {
//			query = builder.keyword().onField("address.geocodedZip").matching(location.getName()).createQuery();
//		} else if (AddressType.CITY == location.getLocationType()) {
//			query = builder
//					.bool()
//					.must(builder.keyword().onField("address.geocodedCity").matching(location.getName()).createQuery())
//					.must(builder.keyword().onField("address.geocodedState").matching(cacheManager.getStateByStateFp(location.getState()))
//							.createQuery()).createQuery();
//		} else if (AddressType.COUNTY == location.getLocationType()) {
//			query = builder
//					.bool()
//					.must(builder.keyword().onField("address.geocodedCounty").matching(location.getName()).createQuery())
//					.must(builder.keyword().onField("address.geocodedState").matching(cacheManager.getStateByStateFp(location.getState()))
//							.createQuery()).createQuery();
//		} else if (AddressType.STATE == location.getLocationType()) {
//			query = builder.keyword().onField("address.geocodedState").matching(location.getName()).createQuery();
//		}
//		return query;
//	}
//
//	private Query buildKeywordQuery(QueryBuilder builder, String keyword) {
//		if (keyword == null || keyword.length() == 0) {
//			return builder.keyword().wildcard().onField("description").matching("*").createQuery();
//		} else {
//			return builder
//					.keyword()
//					.onFields("business.businessName", "description", "specialty", "business.categories.name", "business.specialty",
//							"business.description").matching(keyword).createQuery();
//		}
//	}
//
//	private Query buildRatingQuery(QueryBuilder builder, Integer ratingFilter) {
//		return builder.range().onField("rating").above(ratingFilter.intValue()).createQuery();
//	}
//
//	private Query buildPriceQuery(QueryBuilder builder, List<Integer> priceFilter) {
//		@SuppressWarnings("rawtypes")
//		BooleanJunction junction = null;
//		for (Integer priceRange : priceFilter) {
//			if (junction == null) {
//				junction = builder.bool().should(builder.keyword().onField("price_range").matching(priceRange.intValue()).createQuery());
//			} else {
//				junction.should(builder.keyword().onField("price_range").matching(priceRange.intValue()).createQuery());
//			}
//		}
//		return junction.createQuery();
//	}
//
//	@Override
//	public Address searchAddress(Address address) {
//		logger.info("Search address for " + address);
//		BooleanQuery bQuery = new BooleanQuery();
//		FullTextEntityManager ftem = Search.getFullTextEntityManager(entityManager);
//		QueryBuilder qb = ftem.getSearchFactory().buildQueryBuilder().forEntity(Address.class).get();
//		Query query = qb.keyword().onFields("addressLine1").matching(address.getAddressLine1()).createQuery();
//		bQuery.add(query, BooleanClause.Occur.MUST);
//		query = qb.keyword().onFields("city").matching(address.getCity()).createQuery();
//		bQuery.add(query, BooleanClause.Occur.MUST);
//		query = qb.keyword().onFields("state").matching(address.getState()).createQuery();
//		bQuery.add(query, BooleanClause.Occur.MUST);
//		query = qb.keyword().onFields("zip").matching(address.getZip()).createQuery();
//		bQuery.add(query, BooleanClause.Occur.MUST);
//
//		javax.persistence.Query persistenceQuery = ftem.createFullTextQuery(bQuery, Address.class);
//
//		Address result = null;
//		try{
//			result = (Address)persistenceQuery.getSingleResult();
//		}catch(Exception ex){
//			logger.error(ex.getMessage(), ex);
//		}
//
//		return result;
//	}
//
//	@Override
//	public void reindexOffice() {
//		FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
//		try {
//			fullTextEntityManager.createIndexer(Office.class).batchSizeToLoadObjects(25).cacheMode(CacheMode.IGNORE)
//					.threadsToLoadObjects(5).idFetchSize(150).threadsForSubsequentFetching(20).startAndWait();
//		} catch (InterruptedException ex) {
//			logger.error("Failed to reindex offices.", ex);
//		}
//	}
//
//	@Override
//	public void reindexAddress() {
//		FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
//		try {
//			fullTextEntityManager.createIndexer(Address.class).batchSizeToLoadObjects(25).cacheMode(CacheMode.IGNORE)
//					.threadsToLoadObjects(5).idFetchSize(150).threadsForSubsequentFetching(20).startAndWait();
//		} catch (InterruptedException ex) {
//			logger.error("Failed to reindex offices.", ex);
//		}
//	}
//
//	@Override
//	/**
//	 * Could be filtered 
//	 * 1. keyword, location, neighbors, price, rating.fb cgvjh s3t5
//	 * 2. keyword, address, distance, price, rating
//	 */
//	public SearchResult search(SearchParams params) {
//		if (params != null) {
//			FullTextEntityManager ftem = Search.getFullTextEntityManager(entityManager);
//			QueryBuilder builder = ftem.getSearchFactory().buildQueryBuilder().forEntity(Office.class).get();
//			Query keywordQuery = null;
//			String keyword = params.getKeyword();
//			keywordQuery = buildKeywordQuery(builder, keyword);
//			Query addressQuery = null;
//			GeocodedAddress geocodedAddress = null;
//			String location = params.getLocation();
//			if (location != null && location.length() > 0) {
//				geocodedAddress = geocodeService.geocode(location);
//			}
//			if (geocodedAddress != null) {
//				addressQuery = buildAddressQuery(builder, geocodedAddress, params.getDistance() == null ? 20 : params.getDistance().intValue());
//			}
//
//			Query priceQuery = null;
//			List<Integer> priceFilters = params.getPriceFilters();
//			if (priceFilters != null) {
//				priceQuery = buildPriceQuery(builder, priceFilters);
//			}
//
//			Query ratingQuery = null;
//			Integer ratingFilter = params.getRatingFilter();
//			if (ratingFilter != null) {
//				ratingQuery = buildRatingQuery(builder, ratingFilter);
//			}
//
//			Location target = params.getTargetLocation();
//			List<? extends Location> neighborsFilter = params.getNeighbors();
//			Query locationQuery = null;
//			if (target != null) {
//				locationQuery = buildAddressQuery(builder, target, neighborsFilter, params.getDistance() == null ? 20 : params.getDistance().intValue());
//			}
//			MustJunction mustJunction = builder.bool().must(keywordQuery);
//			boolean multiple = false;
//			if (locationQuery != null) {
//				multiple = true;
//				mustJunction.must(locationQuery);
//			} else if (addressQuery != null) {
//				mustJunction.must(addressQuery);
//				multiple = true;
//			}
//			if (priceQuery != null) {
//				mustJunction.must(priceQuery);
//				multiple = true;
//			}
//			if (ratingQuery != null) {
//				mustJunction.must(ratingQuery);
//				multiple = true;
//			}
//			Query query = keywordQuery;
//			if (multiple)
//				query = mustJunction.createQuery();
//
//			FullTextQuery persistenceQuery = ftem.createFullTextQuery(query, Office.class);
//			Sort sort = null;
//			SortType sortType = params.getSortType();
//			if (SortType.DISTANCE == sortType) {
//				if (geocodedAddress != null && AddressType.ROUTE == geocodedAddress.getAddressType()) {
//					sort = new Sort(new DistanceSortField(geocodedAddress.getPos().getY(), geocodedAddress.getPos().getX(),
//							"address.location"));
//				}
//			} else if (SortType.PRICE_ASC == sortType) {
//				sort = new Sort(new SortField("price", SortField.Type.INT, false));
//			} else if (SortType.PRICE_DSC == sortType) {
//				sort = new Sort(new SortField("price", SortField.Type.INT, true));
//			} else if (SortType.RATING == sortType) {
//				sort = new Sort(new SortField("rating", SortField.Type.INT));
//			} else if (SortType.MOST_REVIEWED == sortType) {
//				sort = new Sort(new SortField("reviewCount", SortField.Type.INT));
//			}
//			if (sort != null) {
//				persistenceQuery.setSort(sort);
//			}
//			FacetManager facetManager = persistenceQuery.getFacetManager();
//			FacetingRequest ratingFacetingRequest = builder.facet().name("ratingFaceting").onField("rating_facet").range().from(20).to(29)
//					.from(30).to(39).from(40).to(49).from(50).to(59).from(60).to(69).from(70).to(79).from(80).to(89).from(90).to(99)
//					.above(100).createFacetingRequest();
//			facetManager.enableFaceting(ratingFacetingRequest);
//
//			FacetingRequest priceFacetingRequest = builder.facet().name("priceFaceting").onField("price_facet").range().below(20).from(20)
//					.to(29).from(30).to(39).from(40).to(49).from(50).to(59).from(60).to(69).from(70).to(79).from(80).to(89).from(90).to(99)
//					.above(100).createFacetingRequest();
//			facetManager.enableFaceting(priceFacetingRequest);
//
//			@SuppressWarnings("unchecked")
//			List<Office> offices = persistenceQuery.getResultList();
//			List<Facet> ratingFacets = facetManager.getFacets("ratingFaceting");
//			List<Facet> priceFacets = facetManager.getFacets("priceFaceting");
//			SearchResult searchResult = new SearchResult();
//			if (geocodedAddress != null) {
//				if (AddressType.ZIP == geocodedAddress.getAddressType()) {
//					List<Zip> neighbors = addressService.findAdjacentZips(geocodedAddress.getZip());
//					for (Zip zip : neighbors) {
//						if (zip.getZip().equals(geocodedAddress.getZip())) {
//							searchResult.setTargetLocation(zip);
//							neighbors.remove(zip);
//							break;
//						}
//					}
//
//					searchResult.setLocationFilter(neighbors);
//				} else if (AddressType.CITY == geocodedAddress.getAddressType()) {
//					List<Place> neighbors = addressService.findAdjacentPlaces(geocodedAddress.getCity(),
//							stateDao.findStatefpByStateName(geocodedAddress.getState()));
//					for (Place place : neighbors) {
//						if (place.getName().equalsIgnoreCase(geocodedAddress.getCity())
//								&& cacheManager.getStateByStateFp(place.getStatefp()).equalsIgnoreCase(geocodedAddress.getState())) {
//							searchResult.setTargetLocation(place);
//							neighbors.remove(place);
//							break;
//						}
//					}
//					searchResult.setLocationFilter(neighbors);
//				} else if (AddressType.COUNTY == geocodedAddress.getAddressType()) {
//					List<County> neighbors = addressService.findAdjacentCounties(geocodedAddress.getCounty(),
//							stateDao.findStatefpByStateName(geocodedAddress.getState()));
//					for (County county : neighbors) {
//						if (county.getName().equalsIgnoreCase(geocodedAddress.getCounty())
//								&& cacheManager.getStateByStateFp(county.getStatefp()).equalsIgnoreCase(geocodedAddress.getState())) {
//							searchResult.setTargetLocation(county);
//							neighbors.remove(county);
//							break;
//						}
//					}
//					searchResult.setLocationFilter(neighbors);
//				} else if (AddressType.STATE == geocodedAddress.getAddressType()) {
//					List<State> neighbors = addressService.findAdjacentStates(geocodedAddress.getState());
//					for (State state : neighbors) {
//						if (state.getState().equalsIgnoreCase(geocodedAddress.getState())) {
//							searchResult.setTargetLocation(state);
//							neighbors.remove(state);
//							break;
//						}
//					}
//					searchResult.setLocationFilter(neighbors);
//				}else if(AddressType.ROUTE == geocodedAddress.getAddressType()){
//					Location loc = LocationFactory.getInstance(params.getLocation(), AddressType.ROUTE, geocodedAddress.getState(), geocodedAddress.getLatitude(), geocodedAddress.getLongitude());
//					searchResult.setTargetLocation(loc);
//				}
//			}
//
//			searchResult.setOffices(offices);
//			searchResult.setRatingFacets(ratingFacets);
//			searchResult.setPriceFacets(priceFacets);
//			for (Facet facet : ratingFacets) {
//				logger.info(facet.toString());
//			}
//			ftem.close();
//			return searchResult;
//		}
//		return null;
//	}
//}
